/**
 * 根据 ECMAScript 规范，这个符号作为一个属性表示“一个方法，
 * 该方法决定一个构造器对象是否认可一个对象是它的实例。由 instanceof 操作符使用”。
 * instanceof 操作符可以用来确定一个对象实例的原型链上是否有原型。
 */

/**
 * instanceof 的典型使用场景
 */
function Foo1() {}
let f1 = new Foo1()
console.log(f1 instanceof Foo1) // true

class Bar1 {}
let b1 = new Bar1()
console.log(b1 instanceof Bar1) // true

/**
 * 在 ES6 中，instanceof 操作符会使用 Symbol.hasInstance 函数来确定关系。
 * 以 Symbol.hasInstance 为键的函数会执行同样的操作，只是操作数对调了一下
 */
function Foo() {}
let f2 = new Foo()
console.log(Foo[Symbol.hasInstance](f2)) // true

class Bar2 {}
let b2 = new Bar2()
console.log(Bar2[Symbol.hasInstance](b2)) // true

/**
 * 这个属性定义在 Function 的原型上，因此默认在所有函数和类上都可以调用。
 * 由于 instanceof 操作符会在原型链上寻找这个属性定义，就跟在原型链上寻找其他属性一样，
 * 因此可以在继承的类上通过静态方法重新定义这个函数
 */
class Bar3 {}
class Baz extends Bar3 {
  static [Symbol.hasInstance]() {
    return false
  }
}

let b3 = new Baz()
console.log(Bar3[Symbol.hasInstance](b3)) // false
console.log(b3 instanceof Bar3) // true
console.log(Baz[Symbol.hasInstance](b3)) // false
